﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using HandScreen.DataMining;
using HandScreen.Views;
using System.Threading;
using System.Windows.Threading;
using System.Diagnostics;

namespace HandScreen
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, ISuspendable
    {
        const int movementThreshold = 40;
        const int movementThresholdPercent = 40;
        const int returnThresholdPercent = 70;
        const int movementTimeThreshold = 1000;
        const int movementDelay = 1000;
        const int automaticSlideDelay = 10000;
        private int screenWidth = 1920;
        private int screenHeight = 1080;
        const int lostTimeOutDelay = 3000;

        private Point lastPosition;
        private int lastTime;
        private int focusedPanel;
        private List<Border> panels;
        private List<Color> panelColors;

        private Boolean automaticMode;
        private bool alive;
        private int firstMouseMovement;
        private int lastMouseMovement;
        private Point firstPosition;
        private bool hasSwitched;

        public MainWindow()
        {
            alive = true;
            InitializeComponent();
            panels = new List<Border>();
            panelColors = new List<Color>();
            focusedPanel = 0;
            lastTime = 0;

            panels.Add(blueB);
            panelColors.Add(((SolidColorBrush)blueB.Background).Color);
            blueB.Background = Brushes.Transparent;
            panels.Add(redB);
            panelColors.Add(((SolidColorBrush)redB.Background).Color);
            redB.Background = Brushes.Transparent;
            panels.Add(yellowB);
            panelColors.Add(((SolidColorBrush)yellowB.Background).Color);
            yellowB.Background = Brushes.Transparent;
            panels.Add(greenB);
            panelColors.Add(((SolidColorBrush)greenB.Background).Color);
            greenB.Background = Brushes.Transparent;
            panels.Add(lightBlueB);
            panelColors.Add(((SolidColorBrush)lightBlueB.Background).Color);
            lightBlueB.Background = Brushes.Transparent;

            SolidColorBrush selectionBrush = (SolidColorBrush)selectionIcon.Background;
            selectionBrush.Opacity = 0.2;
            this.RegisterName("selectionBrush", selectionBrush);
            SolidColorBrush selectionBorderBrush = (SolidColorBrush)selectionIcon.BorderBrush;
            this.RegisterName("selectionBorderBrush", selectionBorderBrush);

            SolidColorBrush mainGridBrush = (SolidColorBrush)mainGrid.Background;
            this.RegisterName("mainGridBrush", mainGridBrush);
            SolidColorBrush iconsBorderBrush = (SolidColorBrush)iconsBorder.BorderBrush;
            this.RegisterName("iconsBorderBrush", iconsBorderBrush);
            SolidColorBrush iconsBackBrush = (SolidColorBrush)iconsBorder.Background;
            this.RegisterName("iconsBackBrush", iconsBackBrush);

            IScrollable vtView = new VasttrafikContainerView(); //3980 korsvägen, 4490 Lindholmen
            blueB.Child = (VasttrafikContainerView)vtView;

            IScrollable rtView = new RestaurantsView();
            redB.Child = (RestaurantsView)rtView;

            IScrollable chView = new ChalmersNewsView();
            yellowB.Child = (ChalmersNewsView)chView;

            IScrollable weView = new WeatherView();
            greenB.Child = (WeatherView)weView;

            IScrollable scView = new TimeEditView();
            lightBlueB.Child = (TimeEditView)scView;

            Thread watcher = new Thread(movementWatcher);
            watcher.Start();

            automaticMode = false;
            Thread automatedSlides = new Thread(automaticSlider);
            automatedSlides.Start();
        }

        private void movementWatcher()
        {
            //Wait for one seconds for gui to start up
            Thread.Sleep(1000);
            //Initialize scrolling in the panels
            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(
                        delegate()
                        {
                            foreach (Border panel in panels)
                            {
                                //((IScrollable)panel.Child).scrollUp();
                            }
                        }
                    ));

            automaticMode = false;
            this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(
                delegate()
                {
                    enableManualMode();
                }
            ));

            //Watch for movements
            int newTime = 0;
            while (alive)
            {
                newTime = lastMouseMovement;
                Thread.Sleep(5000);
                if (newTime == lastMouseMovement)
                {
                    automaticMode = true;
                    this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(
                        delegate()
                        {
                            disableManualMode();
                        }
                    ));
                    while (newTime == lastMouseMovement && alive)
                    {
                        newTime = lastMouseMovement;
                        Thread.Sleep(500);
                    }

                    automaticMode = false;
                    this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(
                        delegate()
                        {
                            enableManualMode();
                        }
                    ));
                }
            }
        }

        private void automaticSlider()
        {
            while (alive)
            {
                while (automaticMode && alive)
                {
                    this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(
                        delegate()
                        {
                            if (((IScrollable)panels[focusedPanel].Child).CanScrollDown())
                            {
                                ((IScrollable)panels[focusedPanel].Child).scrollDown();
                            }
                            else
                            {
                                while (((IScrollable)panels[nextInList()].Child).CanScrollUp())
                                {
                                    ((IScrollable)panels[nextInList()].Child).scrollUp();
                                }
                                switchLeft();
                            }
                        }
                    ));
                    Thread.Sleep(automaticSlideDelay - 1000);
                }
                Thread.Sleep(automaticSlideDelay);
            }
        }

        private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            Console.WriteLine("height: " + this.ActualHeight);
            Console.WriteLine("width: " + this.ActualWidth);
            foreach (Border pan in panels)
            {
                pan.Height = this.ActualHeight - 12;
                pan.Width = this.ActualWidth - 12;
                pan.Margin = new Thickness(0, 0, 0, 0);
                pan.Visibility = System.Windows.Visibility.Hidden;
            }
            ((Border)panels[focusedPanel]).Visibility = System.Windows.Visibility.Visible;
            screenHeight = (int)this.ActualHeight;
            screenWidth = (int)this.ActualWidth;
        }

        private void switchLeft()
        {
            Border headPanel = panels[focusedPanel];
            focusedPanel = nextInList();
            Border trailPanel = panels[focusedPanel];
            trailPanel.Margin = new Thickness(this.ActualWidth, 0, 0, 0);
            trailPanel.Visibility = System.Windows.Visibility.Visible;

            ThicknessAnimation headAnim
                = new ThicknessAnimation
                {
                    From = new Thickness(0, 0, 0, 0),
                    To = new Thickness(-(this.ActualWidth * 2), 0, 0, 0),
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };

            ThicknessAnimation trailAnim
                = new ThicknessAnimation
                {
                    From = new Thickness(this.ActualWidth, 0, 0, 0),
                    To = new Thickness(0, 0, 0, 0),
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };

            headPanel.BeginAnimation(Border.MarginProperty, headAnim);
            trailPanel.BeginAnimation(Border.MarginProperty, trailAnim);
            //System.Threading.Thread.Sleep(1000);
            //headPanel.Visibility = System.Windows.Visibility.Hidden;

            ThicknessAnimation selectionAnim
                = new ThicknessAnimation
                {
                    From = selectionIcon.Margin,
                    To = new Thickness(focusedPanel * selectionIcon.Width + 5, 5, 5, 5),
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            selectionIcon.BeginAnimation(Border.MarginProperty, selectionAnim);

            ColorAnimation selectionColorAnim
                = new ColorAnimation
                {
                    //From = ((SolidColorBrush)selectionIcon.Background).Color,
                    To = panelColors[focusedPanel],
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            Storyboard.SetTargetName(selectionColorAnim, "selectionBrush");
            Storyboard.SetTargetProperty(
            selectionColorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard selectionColorStoryboard = new Storyboard();
            selectionColorStoryboard.Children.Add(selectionColorAnim);
            selectionColorStoryboard.Begin(this);

            ColorAnimation selectionBorderColorAnim
                = new ColorAnimation
                {
                    //From = ((SolidColorBrush)selectionIcon.Background).Color,
                    To = panelColors[focusedPanel],
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            Storyboard.SetTargetName(selectionBorderColorAnim, "selectionBorderBrush");
            Storyboard.SetTargetProperty(
            selectionBorderColorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard selectionBorderColorStoryboard = new Storyboard();
            selectionBorderColorStoryboard.Children.Add(selectionBorderColorAnim);
            selectionBorderColorStoryboard.Begin(this);
        }

        private void switchRight()
        {
            Border headPanel = panels[focusedPanel];
            focusedPanel = prevInList();
            Border trailPanel = panels[focusedPanel];
            trailPanel.Margin = new Thickness(-(this.ActualWidth * 2), 0, 0, 0);
            trailPanel.Visibility = System.Windows.Visibility.Visible;

            ThicknessAnimation headAnim
                = new ThicknessAnimation
                {
                    From = new Thickness(0, 0, 0, 0),
                    To = new Thickness(this.ActualWidth, 0, 0, 0),
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };

            ThicknessAnimation trailAnim
                = new ThicknessAnimation
                {
                    From = new Thickness(-(this.ActualWidth * 2), 0, 0, 0),
                    To = new Thickness(0, 0, 0, 0),
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };

            headPanel.BeginAnimation(Border.MarginProperty, headAnim);
            trailPanel.BeginAnimation(Border.MarginProperty, trailAnim);

            ThicknessAnimation selectionAnim
                = new ThicknessAnimation
                {
                    From = selectionIcon.Margin,
                    To = new Thickness(focusedPanel * selectionIcon.Width + 5, 5, 5, 5),
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            selectionIcon.BeginAnimation(Border.MarginProperty, selectionAnim);

            ColorAnimation selectionColorAnim
                = new ColorAnimation
                {
                    //From = ((SolidColorBrush)selectionIcon.Background).Color,
                    To = panelColors[focusedPanel],
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            Storyboard.SetTargetName(selectionColorAnim, "selectionBrush");
            Storyboard.SetTargetProperty(
            selectionColorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard selectionColorStoryboard = new Storyboard();
            selectionColorStoryboard.Children.Add(selectionColorAnim);
            selectionColorStoryboard.Begin(this);

            ColorAnimation selectionBorderColorAnim
                = new ColorAnimation
                {
                    //From = ((SolidColorBrush)selectionIcon.Background).Color,
                    To = panelColors[focusedPanel],
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            Storyboard.SetTargetName(selectionBorderColorAnim, "selectionBorderBrush");
            Storyboard.SetTargetProperty(
            selectionBorderColorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard selectionBorderColorStoryboard = new Storyboard();
            selectionBorderColorStoryboard.Children.Add(selectionBorderColorAnim);
            selectionBorderColorStoryboard.Begin(this);
        }

        private int nextInList()
        {
            if (focusedPanel == panels.Count - 1)
            {
                return 0;
            }
            else
            {
                return focusedPanel + 1;
            }
        }

        private int prevInList()
        {
            if (focusedPanel == 0)
            {
                return panels.Count - 1;
            }
            else
            {
                return focusedPanel - 1;
            }
        }

        private void mouseCatcher_MouseMove(object sender, MouseEventArgs e)
        {
            //oldMouseMove(sender, e);
            newMouseMove(sender, e);
        }

        private void newMouseMove(object sender, MouseEventArgs e)
        {
            Point newPosition = e.GetPosition(mouseCatcher);
            lastMouseMovement = e.Timestamp;
            if (!hasSwitched)
            {
                if (lastMouseMovement - firstMouseMovement < movementTimeThreshold && firstPosition != new Point(0, 0))
                {
                    debug.Text = "" + (firstPosition.X - newPosition.X) + " " + (screenWidth * ((double)movementThresholdPercent / 100)) + " " + ((screenWidth * ((double)movementThresholdPercent / 100)) * ((double)returnThresholdPercent / 100));
                    if (firstPosition.X - newPosition.X > (screenWidth * ((double)movementThresholdPercent / 100)))
                    {
                        switchLeft();
                        hasSwitched = true;
                    }
                    else if (firstPosition.X - newPosition.X < -(screenWidth * ((double)movementThresholdPercent / 100)))
                    {
                        switchRight();
                        hasSwitched = true;
                    }
                    else if (firstPosition.Y - newPosition.Y > (screenHeight * ((double)movementThresholdPercent / 100)))
                    {
                        ((IScrollable)panels[focusedPanel].Child).scrollDown();
                        hasSwitched = true;
                    }
                    else if (firstPosition.Y - newPosition.Y < -(screenHeight * ((double)movementThresholdPercent / 100)))
                    {
                        ((IScrollable)panels[focusedPanel].Child).scrollUp();
                        hasSwitched = true;
                    }
                }
                else
                {
                    firstMouseMovement = lastMouseMovement;
                    firstPosition = newPosition;
                }
            }
            //else if (newPosition.X < (firstPosition.X / ((double)returnThresholdPercent / 100))
            //    && newPosition.X > (firstPosition.X * ((double)returnThresholdPercent / 100))
            //    && newPosition.Y < (firstPosition.Y / ((double)returnThresholdPercent / 100))
            //    && newPosition.Y > (firstPosition.Y * ((double)returnThresholdPercent / 100)))
            //{
            else if (newPosition.X < ((this.ActualHeight/2) / ((double)returnThresholdPercent / 100))
                && newPosition.X > ((this.ActualHeight / 2) * ((double)returnThresholdPercent / 100))
                && newPosition.Y < ((this.ActualWidth / 2) / ((double)returnThresholdPercent / 100))
                && newPosition.Y > ((this.ActualWidth / 2) * ((double)returnThresholdPercent / 100)))
            {
                debug.Text = "BACK!";
                firstMouseMovement = lastMouseMovement;
                firstPosition = newPosition;
                hasSwitched = false;
            }
            else if (lastMouseMovement - firstMouseMovement > lostTimeOutDelay)
            {
                firstMouseMovement = lastMouseMovement;
                firstPosition = newPosition;
                hasSwitched = false;
            }

            lastPosition = newPosition;
        }

        private void oldMouseMove(object sender, MouseEventArgs e)
        {
            Point newPosition = e.GetPosition(mouseCatcher);
            if (lastPosition != new Point(0, 0) && newPosition != null)
            {
                //Console.WriteLine(lastPosition.X - newPosition.X);
                if (lastPosition.X - newPosition.X > movementThreshold
                    && e.Timestamp - lastTime > movementDelay)
                {
                    lastTime = e.Timestamp;
                    switchLeft();
                }
                else if (lastPosition.X - newPosition.X < -movementThreshold
                    && e.Timestamp - lastTime > movementDelay)
                {
                    lastTime = e.Timestamp;
                    switchRight();
                }
                else if (lastPosition.Y - newPosition.Y > movementThreshold
                    && e.Timestamp - lastTime > movementDelay)
                {
                    lastTime = e.Timestamp;
                    ((IScrollable)panels[focusedPanel].Child).scrollDown();
                }
                else if (lastPosition.Y - newPosition.Y < -movementThreshold
                    && e.Timestamp - lastTime > movementDelay)
                {
                    lastTime = e.Timestamp;
                    ((IScrollable)panels[focusedPanel].Child).scrollUp();
                }
            }
            lastPosition = newPosition;
        }

        private void mouseCatcher_MouseDown(object sender, MouseButtonEventArgs e)
        {
            //switchRight();
            enableManualMode();
        }

        private void mouseCatcher_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (e.Delta > 0)
            {
                ((IScrollable)panels[focusedPanel].Child).scrollUp();
            }
            else if (e.Delta < 0)
            {
                ((IScrollable)panels[focusedPanel].Child).scrollDown();
            }
        }

        private void enableManualMode()
        {
            ColorAnimation selectionColorAnim
                = new ColorAnimation
                {
                    //From = ((SolidColorBrush)selectionIcon.Background).Color,
                    To = Colors.Green,
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            Storyboard.SetTargetName(selectionColorAnim, "mainGridBrush");
            Storyboard.SetTargetProperty(
            selectionColorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard selectionColorStoryboard = new Storyboard();
            selectionColorStoryboard.Children.Add(selectionColorAnim);
            selectionColorStoryboard.Begin(this);

            Color limeOpac = Colors.Green;
            limeOpac.A = 99;
            ColorAnimation selectionBackColorAnim
                = new ColorAnimation
                {
                    //From = ((SolidColorBrush)selectionIcon.Background).Color,
                    To = limeOpac,
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            Storyboard.SetTargetName(selectionBackColorAnim, "iconsBackBrush");
            Storyboard.SetTargetProperty(
            selectionBackColorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard selectionBorderBackStoryboard = new Storyboard();
            selectionBorderBackStoryboard.Children.Add(selectionBackColorAnim);
            selectionBorderBackStoryboard.Begin(this);

            ColorAnimation selectionBorderColorAnim
                = new ColorAnimation
                {
                    //From = ((SolidColorBrush)selectionIcon.Background).Color,
                    To = Colors.Green,
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            Storyboard.SetTargetName(selectionBorderColorAnim, "iconsBorderBrush");
            Storyboard.SetTargetProperty(
            selectionBorderColorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard selectionBorderColorStoryboard = new Storyboard();
            selectionBorderColorStoryboard.Children.Add(selectionBorderColorAnim);
            selectionBorderColorStoryboard.Begin(this);
        }

        private void disableManualMode()
        {
            ColorAnimation selectionColorAnim
                = new ColorAnimation
                {
                    //From = ((SolidColorBrush)selectionIcon.Background).Color,
                    To = Colors.Black,
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            Storyboard.SetTargetName(selectionColorAnim, "mainGridBrush");
            Storyboard.SetTargetProperty(
            selectionColorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard selectionColorStoryboard = new Storyboard();
            selectionColorStoryboard.Children.Add(selectionColorAnim);
            selectionColorStoryboard.Begin(this);

            Color limeOpac = Colors.Black;
            limeOpac.A = 51;
            ColorAnimation selectionBackColorAnim
                = new ColorAnimation
                {
                    //From = ((SolidColorBrush)selectionIcon.Background).Color,
                    To = limeOpac,
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            Storyboard.SetTargetName(selectionBackColorAnim, "iconsBackBrush");
            Storyboard.SetTargetProperty(
            selectionBackColorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard selectionBorderBackStoryboard = new Storyboard();
            selectionBorderBackStoryboard.Children.Add(selectionBackColorAnim);
            selectionBorderBackStoryboard.Begin(this);

            ColorAnimation selectionBorderColorAnim
                = new ColorAnimation
                {
                    //From = ((SolidColorBrush)selectionIcon.Background).Color,
                    To = Colors.Black,
                    Duration = new Duration(TimeSpan.FromSeconds(1))
                };
            Storyboard.SetTargetName(selectionBorderColorAnim, "iconsBorderBrush");
            Storyboard.SetTargetProperty(
            selectionBorderColorAnim, new PropertyPath(SolidColorBrush.ColorProperty));
            Storyboard selectionBorderColorStoryboard = new Storyboard();
            selectionBorderColorStoryboard.Children.Add(selectionBorderColorAnim);
            selectionBorderColorStoryboard.Begin(this);
        }

        public void suspend()
        {
            foreach (Border pan in panels)
            {
                ((ISuspendable)pan.Child).suspend();
            }
            alive = false;
            Close();
        }

        private void mouseCatcher_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                Console.Write("CLOSE");
                this.suspend();
            }
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                Console.Write("CLOSE");
                this.suspend();
            }
        }
    }
}
